# -*- coding: utf-8 -*-
'''
Interface with TGScheduler to provide a solid pythonic cron-like scheduler. Use slots
to access reminder information from the database.
'''
from lifepyscle.model import *
from lifepyscle.model import DBSession as session
import transaction # rw mode because we want to mark the 'pending' reminder as 'dispatched'
from TGScheduler import start_scheduler
from TGScheduler.scheduler import add_interval_task, add_weekday_task, add_single_task
from tg import config
import sys
import logging
import datetime
from datetime import datetime
from turbomail import Message
import transaction as t
#TODO find out why config.get('scheduler_wakeup') returns None
global wakeup
wakeup = 120
log = logging.getLogger(__name__)

def getTriggerDateFromEvent(event,trigger):
    ''' Given the event and the trigger, return the trigger Date '''
    trigger_delta = datetime.timedelta(days=trigger)
    return event.starts-trigger_delta

def getPendingAll():
    ''' pull all pending reminders out of the database '''
    try:
        AllPending = session.query(Reminder).filter(Reminder.status==0).all()
    except:
        raise
    else:
        if not AllPending:
            return [] # is this safe?
        else:
            return AllPending

def getPendingToday():
    ''' pull all pending reminders for today out of the database '''
    pass

def markDispatched(rmd):
    ''' set status field to dispatched '''
    rmd.status = 1
    try:
        t.commit()
    except Exception,e:
        log.error(str(e))
    else:
        log.info("Set status of reminder id %d to %d"%(rmd.reminder_id,rmd.status))

def markFailed(rmd):
    ''' set status field to failed '''
    rmd.status = 2
    try:
        t.commit()
    except Exception,e:
        log.error(str(e))
    else:
        log.info("Set status of reminder %d to %d"%(rmd.reminder_id,rmd.status))

def dispatch(rmd):
    ''' actually do the dispatch and call markDispatched or markFailed'''
    log.info("Sending a reminder mail for reminder id %d"%rmd.reminder_id)
    try:
        message = Message("lifepyscle@foxhall.de", "cfarrell1980@gmail.com", "Reminder for %s on record %s"%(rmd.event.title,rmd.event.record.title))
        message.plain = "%s"%rmd.message
        message.send()
    except Exception,e:
        markFailed(rmd)
        raise 
    else:
        markDispatched(rmd)
        return True

def manageReminder(allPending=False):
    ''' wrapper to call all the above singular methods '''
    try:
        Pending = getPendingAll() #this gets only non-dispatched reminders
    except Exception,e:
        log.error("Tech failed to retrieve reminders for all time going forward: %s"%str(e))
    else:
        log.info("Retrieved %d reminders for all time going forward"%len(Pending))
        # now check if any of them are today
        now = datetime.utcnow()
        td = (now.year,now.month,now.day)
        for x in Pending:
            trg = x.triggerDate
            ymd = (trg.year,trg.month,trg.day)
            if ymd == td:
                try:
                    dispatch(x)
                except Exception,e:
                    log.error(str(e))
                else:
                    log.info("Successfully send reminder mail")

def schedule():
    """ start scheduler and setup recurring tasks """

    if "shell" in sys.argv: # disable cron in paster shell mode
        return

    log.info("Starting Scheduler Manager using %d wakeup"%wakeup)
    start_scheduler()
    # ================ #
    # Add cron tasks here
    # Run once a day
    #add_weekday_task(action=testTask, weekdays=range(1-8), timeonday=(14, 36))

    # run at intervalsa
    add_interval_task(action=manageReminder, taskname="manageReminder", initialdelay=1, interval=wakeup)

    # run this once and forgot, useful for long running backgound tasks
    #add_single_task(action=testTask, initialdelay=0, args=[request.user.email_address] )
    #add_single_task(action=testTask, initialdelay=0, args=['cfarrell@suse.de'] )
